// 18.1 动态多态（Dynamic Polymorphism）
// 动态多态是 C++ 中传统的、基于虚函数的多态机制，它与模板的静态多态形成对比。在讨论模板多态前，先理解动态多态的特点很重要。

// --------------------------------------------------------------
// 动态多态的核心特点
// 1.基于继承和虚函数：通过基类定义接口，派生类重写虚函数实现多态。
// 2.运行时绑定：函数调用在运行时才确定具体执行哪个版本（通过虚函数表）。
// 3.类型擦除：使用基类指针/引用，不需要知道具体派生类类型。

// --------------------------------------------------------------
// 动态多态的典型例子
// 基类定义接口
class Shape
{
public:
    virtual ~Shape() = default;
    virtual void draw() const = 0; // 纯虚函数
    virtual double area() const = 0;
};

// 派生类实现接口
class Circle : public Shape
{
private:
    double radius;

public:
    Circle(double r) : radius(r) {}

    void draw() const override
    {
        std::cout << "Drawing a circle\n";
    }

    double area() const override
    {
        return 3.14159 * radius * radius;
    }
};

class Rectangle : public Shape
{
private:
    double width, height;

public:
    Rectangle(double w, double h) : width(w), height(h) {}

    void draw() const override
    {
        std::cout << "Drawing a rectangle\n";
    }

    double area() const override
    {
        return width * height;
    }
};

// 使用多态
void drawShape(const Shape &shape)
{
    shape.draw(); // 运行时决定调用哪个draw()
}

int main()
{
    Circle c(5.0);
    Rectangle r(4.0, 3.0);

    drawShape(c); // 输出: Drawing a circle
    drawShape(r); // 输出: Drawing a rectangle

    // 存储不同类型的对象
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Circle>(2.0));
    shapes.push_back(std::make_unique<Rectangle>(3.0, 4.0));

    // 多态调用
    for (const auto &shape : shapes)
    {
        shape->draw();
        std::cout << "Area: " << shape->area() << std::endl;
    }
}

// ------------------------------------------------------------
// 动态多态的优缺点
// 优点：
// 1.运行时灵活性：可以在运行时决定使用哪种具体类型。
// 2.接口统一：所有派生类通过相同的接口被访问。
// 3.类型安全：基类指针/引用只能调用基类定义的方法。
// 4.开放扩展：可以添加新的派生类而不修改使用代码。

// 缺点：
// 1.运行时开销：虚函数调用比普通函数调用慢（需要查虚函数表）。
// 2.内存开销：每个带虚函数的对象都有额外的虚函数表指针。
// 3.编译期不透明：编译器无法看到具体调用哪个函数，限制了优化。
// 4.类型必须相关：只有继承关系的类才能共用接口。

// ------------------------------------------------------------
// 动态多态与模板多态的对比
// 动态多态（虚函数）和模板多态（静态多态）是 C++ 中两种不同的多态机制：
// 1.绑定时机：
//  动态多态：运行时绑定
//  模板多态：编译时绑定
// 2.类型关系：
//  动态多态：要求继承关系
//  模板多态：只要求语法兼容（鸭子类型）
// 3.代码生成：
//  动态多态：一个虚函数的实现
//  模板多态：每种类型一份代码实例

// ------------------------------------------------------------
// 总结
// 动态多态是 C++ 面向对象编程的核心特性，通过继承和虚函数实现。它提供了运行时的灵活性，但有一定的性能开销。理解动态多态的特点，有助于我们更好地理解模板提供的静态多态机制，以及在不同场景下如何选择合适的多态方式。
